﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ITG.Helper;
using ITG.Services;
using ITG.Designer;
using DALT.Utility;
using DALT.Controls;
using DALT.Controls.Converters;


namespace ITG.DesignerItems
{
    public class DesignerItemBaseVM : ObservableObject
    {
        #region Enums

        private enum PF : int
        {
            Prefix = 0,
            Modifier = 1,
            Result = 2,
            Status = 3,
            Value = 4,
            LinkGroup = 5,
            Units = 6,
            BoxOffset = 7,
            InlineTextboxWidth = 8,
            ComponentSequence = 9,
            IndexToReferenceList = 10,
            NarrativeGroupAssignment = 11,
            CHKYCaption = 12,
            CHKNCaption = 13,
            BitFlags = 14,
            LimitMax = 15,
            LimitMin = 16,
            RibbonTriggerId = 17,
            ClusterId = 18,
            ParentRibbonId = 19,
            RadioButtonGroup = 20,
            ImageId = 21,
            HotSpotSetId = 22,
            ParentFrame = 23,
            CodeMapping = 24,
            UserAssignedSubgroup = 25
        };

        #endregion


        #region Members

        private double left, top, width, height;
        private bool isSelected;
        protected bool isMedcinItem;

        private int tab;
        private int medcinId;
        protected string controlType;
        private int controlFlag;
        public string ToolBoxImageUrl { get; protected set; } 
        private string tooltip;

        private double minWidth = 20;
        private double maxWidth = 1000;
        private double minHeight = 20;
        private double maxHeight = 1000;
        private double defWidth = 100;
        private double defHeight = 20;
        
        #endregion


        #region Constructors

        public DesignerItemBaseVM() : base()
        {
            Init();
        }

        #endregion


        #region Size/Position Properties

        public int Tab
        { 
            // get { return this.tab; }
            get
            {
                if (ParentTab != null) return ParentTab.Index + 1;
                else return -1;// AHLTA "tabs" are not 0-based, since 0 is used for resources
            }
        }

        public double Left
        {
            get
            {
                return left;
            }
            set
            {
                value = Math.Round(value, MidpointRounding.AwayFromZero);
                if (left != value)
                {
                    left = value;
                    NotifyPropertyChanged("Left");
                    NotifyPropertyChanged("Right");
                }
            }
        }

        public double Top
        {
            get
            {
                return top;
            }
            set
            {
                value = Math.Round(value, MidpointRounding.AwayFromZero);
                if (top != value)
                {
                    top = value;
                    NotifyPropertyChanged("Top");
                    NotifyPropertyChanged("Bottom");
                }
            }
        }

        public double Width
        {
            get
            {
                return this.width;
            }

            set
            {
                value = Math.Round(value, MidpointRounding.AwayFromZero);
                if (this.width != value)
                {
                    this.width = value;
                    EnforceSizeConstraints();
                    NotifyPropertyChanged("Width");
                    NotifyPropertyChanged("Left"); // may not need both of these
                    NotifyPropertyChanged("Right");
                }
            }
        }

        public double Height
        {
            get
            {
                return this.height;
            }

            set
            {
                value = Math.Round(value, MidpointRounding.AwayFromZero);
                if (this.height != value)
                {
                    this.height = value;
                    EnforceSizeConstraints();
                    NotifyPropertyChanged("Height");
                    NotifyPropertyChanged("Top"); // may not need both of these
                    NotifyPropertyChanged("Bottom");
                }
            }
        }

        public double Right
        {
            get
            {
                return (Left + Width - 1);
                
            }
        }

        public double Bottom
        {
            get
            {
                return (Top + Height - 1);
            }
        }

        public double MinWidth { get { return this.minWidth; } }
        public double MaxWidth { get { return this.maxWidth; } }
        public double MinHeight { get { return this.minHeight; } }
        public double MaxHeight { get { return this.maxHeight; } }

        #endregion


        #region General Properties

        // reference to parent designer - this is set in DesignerVM.ExecuteAddItemCommand
        public DesignerVM ParentForm { get; set; }

        // reference to parent tab
        public DesignerTabVM ParentTab { get; set; }

        public bool IsMedcinItem { get { return isMedcinItem; } }

        public string ControlType
        { get { return this.controlType; } }

        public int ControlFlag
        { get { return this.controlFlag; } }

        public string Tooltip
        { get { return this.tooltip; } }

        public int MedcinId
        {
            get { return this.medcinId; }
            set
            {
                if (this.medcinId != value)
                {
                    this.medcinId = value;
                    OnPropertyChanged("MedcinId");
                }
            }
        }

        public string Prefix
        {
            get
            {
                return GetPrefix();
            }
        }

        public string ItemData { get { return GetItemData(); } }

        public string Description { get { return GetDescription(); } }

        #endregion
        

        #region Prefix Properties

        //<Category("Prefix"), Description("(Unknown) Possibly affects placement in note, to differentiate several objects with identical MedcinIDs")>
        //Public Property PF_Prefix() As String = "" '0
        public string PF_Prefix { get; set; }

        //<Category("Prefix"), Description("(Unknown) Possibly enum values - used for wellness levels EX, GD, FR, PR, etc")>
        //Public Property PF_Modifier() As String = "" '1
        public string PF_Modifier { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_Result() As String = "" '2
        public string PF_Result { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_Status() As String = "" '3
        public string PF_Status { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_Value() As String = "" '4
        public string PF_Value { get; set; }

        //<Category("Prefix"), Description("Specifies the object's relative value/order within a linked group, such as radiobuttons (0..5)")>
        //Public Property PF_LinkGroup() As String = "" '5
        public string PF_LinkGroup { get; set; }

        //<Category("Prefix"), Description("Units associated with the control's data, such as cm, days, etc")>
        //Public Property PF_Units() As String = "" '6
        public string PF_Units { get; set; }

        //<Category("Prefix"), Description("(Unknown) Possibly the height of the control? Tends to be 19 in most cases")>
        //Public Property PF_BoxOffset() As String = "19" '7
        private int pf_BoxOffset;
        public int PF_BoxOffset 
        {
            get { return this.pf_BoxOffset; }
            set
            {
                if (this.pf_BoxOffset != value)
                {
                    this.pf_BoxOffset = value;
                    NotifyPropertyChanged("PF_BoxOffset");
                    NotifyPropertyChanged("Height"); // doesn't do anything
                }
            }
        }

        //<Category("Prefix"), Description("Width of an inline textbox component, as measured in pixels from right to left")>
        //Public Property PF_InlineTextboxWidth() As String = "80" '8
        private int pf_InlineTextboxWidth;
        public int PF_InlineTextboxWidth
        {
            get { return this.pf_InlineTextboxWidth; }
            set
            {
                if (this.pf_InlineTextboxWidth != value)
                {
                    this.pf_InlineTextboxWidth = value;
                    NotifyPropertyChanged("PF_InlineTextboxWidth");
                    NotifyPropertyChanged("Width"); // doesn't do anything
                }
            }
        }
        //public string PF_InlineTextboxWidth { get; set; }

        //<Category("Prefix"), Description("Helps determine the order of the components (ex: YCN)")>
        //Public Property PF_ComponentSequence() As String = "YCN" '9
        public string PF_ComponentSequence { get; set; }

        //<Category("Prefix"), Description("Used to reference a URL object; use 0 for null")>
        //Public Property PF_IndexToReferenceList() As String = "0" '10
        public string PF_IndexToReferenceList { get; set; }

        //<Category("Prefix"), Description("(Unknown) 0 seems to be the default value")>
        //Public Property PF_NarrativeGroupAssignemnt() As String = "0" '11
        public string PF_NarrativeGroupAssignment { get; set; }

        //<Category("Prefix"), Description("The character assigned to the first checkbox component")>
        //Public Property PF_CHKYCaption() As String = "Y" '12
        public string PF_CHKYCaption { get; set; }

        //<Category("Prefix"), Description("The character assigned to the second checkbox component (if any)")>
        //Public Property PF_CHKNCaption() As String = "N" '13
        public string PF_CHKNCaption { get; set; }

        //<Category("Prefix"), Description("Bits 0-1: automatic browse; Bit 2: disable HPI-ROS toggle; Bit 3: disable gender check; Bit 4: ValueSum")>
        //Public Property PF_BitFlags() As String = "" '14
        public string PF_BitFlags { get; set; }

        //<Category("Prefix"), Description("Maximum allowed value")>
        //Public Property PF_LimitMax() As String = "" '15
        public string PF_LimitMax { get; set; }

        //<Category("Prefix"), Description("Minimum allowed value")>
        //Public Property PF_LimitMin() As String = "" '16
        public string PF_LimitMin { get; set; }

        //<Category("Prefix"), Description("Specifies the ribbon to expand when this object is activated")>
        //Public Property PF_RibbonTriggerId() As String = "" '17
        public string PF_RibbonTriggerId { get; set; }

        //<Category("Prefix"), Description("Specifies the cluster that this object belongs to")>
        //Public Property PF_ClusterID() As String = "" '18
        public string PF_ClusterId { get; set; }

        //<Category("Prefix"), Description("Specifies the ribbon that this object belongs to")>
        //Public Property PF_ParentRibbonID() As String = "" '19
        public string PF_ParentRibbonId { get; set; }

        //<Category("Prefix"), Description("Specifies the radio button group that this object belongs to")>
        //Public Property PF_RadioButtonGroup() As String = "" '20
        public string PF_RadioButtonGroup { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_ImageID() As String = "" '21
        public string PF_ImageId { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_HotSpotSetID() As String = "" '22
        public string PF_HotSpotSetId { get; set; }

        //<Category("Prefix"), Description("Specifies the parent frame for all objects other than boxes and grids")>
        //Public Property PF_ParentFrame() As String = "" '23
        public string PF_ParentFrame { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_CodeMapping() As String = "" '24
        public string PF_CodeMapping { get; set; }

        //<Category("Prefix"), Description("(Unknown)")>
        //Public Property PF_UserAssignedSubgroup() As String = "" '25
        public string PF_UserAssignedSubgroup { get; set; }

        #endregion


        #region ItemData Properties

        //<Category("ItemData"), Description("Specifies the font used for the object's caption; F=<FontName As String>")>
        //Public Property ID_FontName() As String = "" 'F=
        private string id_Font = "Arial";
        public string ID_Font 
        {
            get
            {
                return this.id_Font;
            }
            set
            {
                if (this.id_Font != value)
                {
                    this.id_Font = value;
                    OnPropertyChanged("ID_Font");
                }
            }
        }

        //<Category("ItemData"), Description("Specifies whether the object's caption is BOLD; B=<T,F>")>
        //Public Property ID_Bold() As String = "" 'B=
        public string ID_Bold { get; set; }

        //<Category("ItemData"), Description("Specifies whether the object's caption is ITALICIZED; I=<T,F>")>
        //Public Property ID_Italic() As String = "" 'I=
        public string ID_Italic { get; set; }

        //<Category("ItemData"), Description("Specifies whether the object's caption is UNDERLINED; U=<T,F>")>
        //Public Property ID_Underline() As String = "" 'U=
        public string ID_Underline { get; set; }

        //<Category("ItemData"), Description("Specifies the forecolor of the object; C=<AHLTAColor As Integer>")>
        //Public Property ID_ForeColor() As String = "" 'C=
        public string ID_ForeColor { get; set; }

        //<Category("ItemData"), Description("Specifies the backcolor of the object; K=<AHLTAColor As Integer>")>
        //Public Property ID_BackColor() As String = "" 'K=
        public string ID_BackColor { get; set; }

        //<Category("ItemData"), Description("Specifies the BackStyle of an object, where 0 = transparent and 1 = opaque; T=<0,1>")>
        //Public Property ID_BackStyle() As String = "" 'T=
        public string ID_BackStyle { get; set; }

        //<Category("ItemData"), Description("Specifies the BorderStyle of an object; S=<0,1>")>
        //Public Property ID_BorderStyle() As String = "" 'S=
        public string ID_BorderStyle { get; set; }

        //<Category("ItemData"), Description("Specifies the draw width of a Drawing object; W=<?>")>
        //Public Property ID_DrawWidth() As String = "" 'W=
        public string ID_DrawWidth { get; set; }

        //<Category("ItemData"), Description("Specifies the composite image marker style; M=<Integer>")>
        //Public Property ID_ImageMarkerStyle() As String = "" 'M=
        public string ID_ImageMarkerStyle { get; set; }

        //<Category("ItemData"), Description("Specifies the comma-delimited list of chart column item enum values for listview associated with Medcin or Picklist objects; G=<?>")>
        //Public Property ID_ListviewColumnItems() As String = "" 'G=
        public string ID_ListviewColumnItems { get; set; }

        //<Category("ItemData"), Description("Specifies the logic equation or other list, if any, and is always last. It may contain a list of Medcinids for use with an internal drop list pick list. It may contain a list of ImageIDs for use with an imager control object; L=<?>")>
        //Public Property ID_Logic() As String = "" 'L=
        public string ID_Logic { get; set; }

        //<Category("ItemData"), Description("Specifies a unique numeric ID for this object; N=<Integer>")>
        //Public Property ID_ObjectID() As String = "" 'N=
        public string ID_ObjectId { get; set; }

        //<Category("ItemData"), Description("Represents the combined flag values for the options; O=<Integer>")>
        //Public Property ID_Options() As String = "" 'O=
        public string ID_Options { get; set; }

        //<Category("ItemData"), Description("Specifies the tooltip for objects with captions; P=<String>")>
        //Public Property ID_Tooltip() As String = "" 'P=
        public string ID_Tooltip { get; set; }

        //<Category("ItemData"), Description("Specifies the availability of intelligent prompting for a Tree object; I=<?>")>
        //Public Property ID_TreeIntelligentPrompting() As String = "" 'I=
        public string ID_TreeIntelligentPrompting { get; set; }

        //<Category("ItemData"), Description("Specifies the availability of mouse browsing for a Tree object; B=<?>")>
        //Public Property ID_TreeMouseBrowsing() As String = "" 'B=
        public string ID_TreeMouseBrowsing { get; set; }

        //<Category("ItemData"), Description("Specifies the availability of word search for a Tree object; S=<?>")>
        //Public Property ID_TreeWordSearch() As String = "" 'S=
        public string ID_TreeWordSearch { get; set; }

        //<Category("ItemData"), Description("Specifies the ValueBoxChars enum value designating restrictions on what type of characters are allowed in a value box: 0=AllowAll, 1=AllowNumbers, 2=AllowLetters; V=<0,1,2>")>
        //Public Property ID_ValueBoxChars() As String = "" 'V=
        public string ID_ValueBoxChars { get; set; }

        //<Category("ItemData"), Description("Specifies the appearance of checkboxes; Y=<0,1,2,4,5,6>")>
        //Public Property ID_YesNoStyle() As String = "" 'Y=
        public string ID_YesNoStyle { get; set; }

        #endregion


        #region Description Properties

        //<Category("Description"), Description("The caption associated with the control")>
        //Public Property D_Caption() As String = ""
        private string d_Caption = "";
        public string D_Caption 
        {
            get { return this.d_Caption; }
            set
            {
                if (this.d_Caption != value)
                {
                    this.d_Caption = value;
                    NotifyPropertyChanged("D_Caption");
                    NotifyPropertyChanged("Width");
                }
            }
        }

        //<Category("Description"), Description("The default text associated with the control")>
        //Public Property D_Content() As String = ""
        private string d_Content = "";    
        public string D_Content 
        {
            get { return this.d_Content; }
            set
            {
                if (this.d_Content != value)
                {
                    this.d_Content = value;
                    NotifyPropertyChanged("D_Content");
                }
            }
        }

        #endregion


        #region Selection Properties
        
        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                if (isSelected != value)
                {
                    
                    isSelected = value;
                    NotifyPropertyChanged("IsSelected");
                }
            }
        }

        public List<DesignerItemBaseVM> SelectedItems
        {
            get { return ParentTab.SelectedItems; }
        }

        #endregion


        #region Commands

        public MyCommand SelectItemCommand { get; private set; }
        private void ExecuteSelectItemCommand(object param)
        {
            SelectItem((bool)param, !IsSelected);
        }

        private void SelectItem(bool newselect, bool select)
        {
            if (newselect)
            {
                foreach (var designerItemBaseVM in ParentTab.SelectedItems.ToList())
                {
                    designerItemBaseVM.isSelected = false;
                }
            }

            IsSelected = select;
        }

        #endregion


        #region Methods
        
        private void Init()
        {
            //System.Console.WriteLine("Reached DesignerItemBaseVM.Init()");
            SelectItemCommand = new MyCommand(ExecuteSelectItemCommand);
            SetControlDefaults("DesignerItemBase", -1, "DesignerItemBase");
            //System.Console.WriteLine("------------------ParentForm: {0}", ParentForm.ToString());
            //System.Console.WriteLine("==================ParentTab: {0}", ParentTab.ToString());
            //ParentTab = ParentForm.ActiveTab; // a default for testing!
            MedcinId = 0; // a default for testing!
            //ToolBoxImageUrl = "Resources/ToolBoxImages/DesignerItemBase.png";
            
            SetSizeConstraints(100, 20, 1000, 20, 20, 1000); // THIS IS WHAT DETERMINES THE CANVAS SIZE!!!
            EnforceSizeConstraints();
        }

        protected void SetControlDefaults(string controlType, int controlFlag, string tooltip)
        {
            this.controlType = controlType;
            this.controlFlag = controlFlag;
            this.tooltip = tooltip;
        }

        protected void SetSizeConstraints(double defWidth, double minWidth, double maxWidth, double defHeight, double minHeight, double maxHeight)
        {
            //System.Console.WriteLine("Setting size constraints ... {0} {1} {2} {3}",minWidth,maxWidth,minHeight,maxHeight);
            this.defWidth = defWidth;
            this.Width = this.defWidth;
            this.minWidth = minWidth;
            this.maxWidth = maxWidth;
            this.defHeight = defHeight;
            this.Height = this.defHeight;
            this.minHeight = minHeight;
            this.maxHeight = maxHeight;
        }

        private void EnforceSizeConstraints()
        {
            //System.Console.WriteLine("Enforcing size constraints ...");
            if (Width < minWidth) Width = minWidth;
            if (Width > maxWidth) Width = maxWidth;
            if (Height < minHeight) Height = minHeight;
            if (Height > maxHeight) Height = maxHeight;
        }

        private string GetGeneral()
        {
            return String.Format("{0},{1},{2},{3},{4},{5},{6}", Tab, Left, Top, Right, Bottom, MedcinId, ControlFlag);
        }
        
        protected string GetPrefix()
        {
            string prefix = String.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}|{10}|{11}|{12}|{13}|{14}|{15}|{16}|{17}|{18}|{19}|{20}|{21}|{22}|{23}|{24}|{25}",
                PF_Prefix, PF_Modifier, PF_Result, PF_Status, PF_Value,
                PF_LinkGroup, PF_Units, PF_BoxOffset, PF_InlineTextboxWidth, PF_ComponentSequence, 
                PF_IndexToReferenceList, PF_NarrativeGroupAssignment, PF_CHKYCaption, PF_CHKNCaption, PF_BitFlags,
                PF_LimitMax, PF_LimitMin, PF_RibbonTriggerId, PF_ClusterId, PF_ParentRibbonId,
                PF_RadioButtonGroup, PF_ImageId, PF_HotSpotSetId, PF_ParentFrame, PF_CodeMapping,
                PF_UserAssignedSubgroup);
            return TextOps.QuoteWrap(prefix);
        }

        public void SetPrefix(String[] prefix)
        {
            PF_Prefix = prefix[0];
            PF_Modifier = prefix[1];
            PF_Result = prefix[2];
            PF_Status = prefix[3];
            PF_Value = prefix[4];
            PF_LinkGroup = prefix[5];
            PF_Units = prefix[6];
            // PF_BoxOffset = prefix[7];
            PF_BoxOffset = int.Parse(prefix[7]);
            // PF_InlineTextboxWidth = prefix[8];
            PF_InlineTextboxWidth = int.Parse(prefix[8]);
            PF_ComponentSequence = prefix[9];
            PF_IndexToReferenceList = prefix[10];
            PF_NarrativeGroupAssignment = prefix[11];
            PF_CHKYCaption = prefix[12];
            PF_CHKNCaption = prefix[13];
            PF_BitFlags = prefix[14];
            PF_LimitMax = prefix[15];
            PF_LimitMin = prefix[16];
            PF_RibbonTriggerId = prefix[17];
            PF_ClusterId = prefix[18];
            PF_ParentRibbonId = prefix[19];
            PF_RadioButtonGroup = prefix[20];
            PF_ImageId = prefix[21];
            PF_HotSpotSetId = prefix[22];
            PF_ParentFrame = prefix[23];
            PF_CodeMapping = prefix[24];
            PF_UserAssignedSubgroup = prefix[25];
        }

        private string GetItemData()
        {
            // temporarily hardcoded
            return TextOps.QuoteWrap("F=Arial|T=T"); 
        
        }

        private string GetDescription()
        {
            if (string.IsNullOrWhiteSpace(D_Content))
            {
                return TextOps.QuoteWrap(D_Caption);
            }
            else return TextOps.QuoteWrap(D_Caption + "~" + TextOps.ToggleLineReturn(D_Content));
        }

        private void ValidateItem()
        {
            //
        }

        public override string ToString()
        {
            return GetGeneral() + "," +
                GetPrefix() + "," +
                GetItemData() + "," +
                GetDescription();
        }
        
        #endregion
    }
}



/*

#Region "Enums and Flags"

    
    End Enum

    <FlagsAttribute>
    Enum MedcinOption
        None = 0
        fc_HAS_BEEN_EDITED = 1
        fc_DISABLE_MOUSE_BROWSING = 2
        fc_DISABLE_CLUSTER_ON_Y = 8
        fc_DISABLE_CLUSTER_ON_N = 16
        fc_DESIGNER_INVERTED_CONCEPT = 256
    End Enum

    <FlagsAttribute>
    Enum LinkOption
        fc_FIRE_WHEN_LOGIC_TRUE = 1
        fc_RAISE_MESSAGE_WHEN_LOGIC_TRUE = 2
        fc_IS_USER_BUTTON = 4
        fc_IS_AUTONEG_BUTTON = 8
        fc_IS_AUTOPOS_BUTTON = 16
        fc_IS_NEGBLOCK_BUTTON = 32
        fc_IS_POSBLOCK_BUTTON = 64
        fc_IS_FLOWSHEET_BUTTON = 128
        fc_IS_REFERENCE_BUTTON = 256
    End Enum

    <FlagsAttribute>
    Enum RibbonOption
        fc_EXPAND_ON_YES = 1
        fc_COLLAPSE_ON_NO = 2
        fc_HIDE_ON_COLLAPSE = 4
        fc_SHOW_BUTTON = 8
        fc_EXPAND_ON_NO = 16
        fc_COLLAPSE_ON_YES = 32
    End Enum

    <FlagsAttribute>
    Enum PictureOption
        fc_IS_IMAGER_COMPONENT = 2
        fc_SET_POSITIVE_ON_CLICK = 4
        fc_SET_NEGATIVE_ON_CLICK = 8
        fc_SET_PREFIX_ON_CLICK = 16
        fc_SET_VALUE_ON_CLICK = 32
    End Enum

    <FlagsAttribute>
    Enum ListOption
        fc_LIST_ALLOW_NODE_EXPANSION = 2
        fc_LIST_LOGIC = 4 ' disabled=0, enabled=1
        fc_LIST_DISABLE_UNTIL_LOGIC_TRUE = 8
        fc_LIST_ACTIVATE_WHEN_LOGIC_TRUE = 16
        fc_TREEVIEW_RELOCATE_ORIGIN_RELATIVE_OBJECT = 32
        fc_LIST_SORT_INLINE_CAPTIONS = 64
        fc_LISTVIEW_USE_COLOR = 128
        fc_LISTVIEW_AUTO_RESIZE_COLUMNS = 256
    End Enum

    

#End Region


*/